﻿#include "scriptreader.h"
#include <QMessageBox>
#include <QDebug>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonParseError>
#include <QFile>
#include <QJsonDocument>
#include <QRegularExpression>
#include <QRegularExpressionMatch>



ScriptReader::ScriptReader(QObject *parent)
    : QObject{parent}
{}


/**
 * @brief : 根据传入的文件路径参数打开脚本文件，设置成员属性m_jsObj，并返回文件读取结果
 * @param filePath : 文件路径
 * @return : Boolean类型，脚本文件读取成功，且成员属性m_jsObj不为空时返回true，
 *           否则返回false
 */
bool ScriptReader::openFile(const QString& filePath)
{
    bool ret = true;
    // 判断文件是否能打开
    QFile file(filePath);

    if (!file.open(QIODevice::ReadOnly)) {
        QMessageBox::warning(nullptr, u8"警告", filePath + u8"文件打开失败，请检查文件是否存在！error:" + file.errorString() + QString::number(__LINE__));
        file.close();
        ret = false;
    }

    // 创建json对象
    if (ret) {
        QJsonDocument t_jsDoc = QJsonDocument::fromJson(file.readAll());
        QJsonObject jsObj = t_jsDoc.object();
        if(!jsObj.isEmpty()) {
            m_guideway_sheet_object = jsObj[CONFIG_GUIDEWAY_SHEET_KEY].toObject();
            m_data_sheet_object = jsObj[CONFIG_DATA_SHEET_KEY].toObject();
            m_log_file_object = jsObj[CONFIG_LOG_FILE_KEY].toObject();
            m_drawing_info_object = jsObj[CONFIG_DRAWING_INFO_KEY].toObject();
            m_ui_config_array = jsObj[CONFIG_UI_CONFIG_KEY].toArray();

            ret = !m_guideway_sheet_object.isEmpty() &
                !m_data_sheet_object.isEmpty() &
                !m_log_file_object.isEmpty() &
                !m_drawing_info_object.isEmpty() &
                !m_ui_config_array.isEmpty();
        }

        if(!ret)
            QMessageBox::warning(nullptr, u8"警告", filePath + u8"文件读取失败，请检查文件是否满足Json格式！error:" + file.errorString() + QString::number(__LINE__));
    }

    file.close();

    return ret;
}




/**
 * 从配置文件中读取曲线列表，返回每条曲线名称和Y轴的计算公式
 * @param : None
 * @return : QVector<CurveInfo>类型，每个元素为一根曲线的结构体，详见结构体CurveInfo
 */
QVector<ScriptReader::CurveInfo> ScriptReader::getCurveInfo()
{
    QVector<ScriptReader::CurveInfo> ret_list;

    // 读取曲线配置
    QJsonObject curvesObj = m_drawing_info_object[CONFIG_CURVES_KEY].toObject();

    QJsonObject fromLogObj = curvesObj[CONFIG_FROM_LOG_KEY].toObject();
    QJsonObject fromDataSheetObj = curvesObj[CONFIG_FROM_DATA_SHEET_KEY].toObject();

    QJsonArray colorArray = curvesObj[CONFIG_COLORS_KEY].toArray();

    QString axis_x_from_log = getAxisXCaculationFormatString(CONFIG_FROM_LOG_KEY);
    QString axis_x_from_data_sheet = getAxisXCaculationFormatString(CONFIG_FROM_DATA_SHEET_KEY);
    // qDebug()<< "axis_x_from_data_sheet:" << axis_x_from_data_sheet;
    // 读取Y轴配置的字符串
    QJsonArray axis_y_from_log = fromLogObj[CONFIG_AXIS_Y_KEY].toArray();
    QJsonArray axis_y_from_data_sheet = fromDataSheetObj[CONFIG_AXIS_Y_KEY].toArray();

    // 读取曲线名称
    QJsonArray curve_name_from_log = fromLogObj[CONFIG_CURVE_NAME_KEY].toArray();
    QJsonArray curve_name_from_data_sheet = fromDataSheetObj[CONFIG_CURVE_NAME_KEY].toArray();

    // 添加日志文件中相关曲线
    int color_index = 0;    // 颜色索引
    for (int i = 0; i < axis_y_from_log.size(); i++) {
        ScriptReader::CurveInfo curve_info;
        curve_info.name = curve_name_from_log[i].toString();
        curve_info.x_formula = axis_x_from_log;
        curve_info.y_formula = axis_y_from_log[i].toString();
        curve_info.color = colorArray[color_index++].toString();
        curve_info.source = CONFIG_FROM_LOG_KEY;
        ret_list.append(curve_info);
    }
    // 添加data sheet中相关曲线
    for (int i = 0; i < axis_y_from_data_sheet.size(); i++) {
        ScriptReader::CurveInfo curve_info;
        curve_info.name = curve_name_from_data_sheet[i].toString();
        curve_info.x_formula = axis_x_from_data_sheet;
        curve_info.y_formula = axis_y_from_data_sheet[i].toString();
        curve_info.color = colorArray[color_index++].toString();
        curve_info.source = CONFIG_FROM_DATA_SHEET_KEY;
        ret_list.append(curve_info);
    }



    return ret_list;
}



/**
 * 从配置文件中读取坐标轴的显示名称
 * @param axis : 坐标轴名称，CONFIG_AXIS_X_KEY或CONFIG_AXIS_Y_KEY, 参见头文件中的宏
 * @return : QString类型，返回坐标轴的显示名称
 */
QString ScriptReader::getAxisTitle(const QString& axis) const
{
    // 读取曲线配置
    QJsonObject titleObj = m_drawing_info_object[CONFIG_TITLE_KEY].toObject();
    return titleObj[axis].toString();
}


/**
 * 从配置文件中读取坐标轴的显示名称
 * @param axis : 坐标轴名称，CONFIG_AXIS_X_KEY或CONFIG_AXIS_Y_KEY, 参见头文件中的宏
 * @return : QList<int>类型, 返回坐标轴的范围(tickcount, min, max)(等分数，最小值，最大值)
 */
QList<int> ScriptReader::getAxisRange(const QString& axis)
{
    QList<int> ret_list;
    // 读取曲线配置
    if (!m_drawing_info_object.isEmpty()) {
        QJsonObject axisObj = m_drawing_info_object[CONFIG_RANGE_KEY].toObject();
        QJsonArray array = axisObj[axis].toArray();
        for(auto const& val : std::as_const(array)) {
            ret_list.append(val.toInt());
        }
    }
    return ret_list;
}


/**
 * 获取X轴计算公式字符串
 * @param key: 三级key, CONFIG_FROM_LOG_KEY或CONFIG_FROM_DATA_SHEET_KEY
 * @return : QString类型, 返回X轴坐标的计算公式字符串
 */
QString ScriptReader::getAxisXCaculationFormatString(const QString& key) const
{
    // 读取曲线配置
    if (m_drawing_info_object.isEmpty()) return "";
    QJsonObject curvesObj = m_drawing_info_object[CONFIG_CURVES_KEY].toObject();
    QJsonObject axisObj = curvesObj[key].toObject();

    return axisObj[CONFIG_AXIS_X_KEY].toArray()[0].toString();
}

QHash<QString, int> ScriptReader::getGuideWaySheetConfig()
{
    QHash<QString, int> ret_hash;

    // const auto keys = m_guideway_sheet_object.keys();
    // for (const auto& key : keys) {
    //     int value = m_guideway_sheet_object[key].toInt();
    //     ret_hash[key] = value;
    // }


    // 读取曲线配置
    if (!m_guideway_sheet_object.isEmpty()) {
        int track_id = m_guideway_sheet_object[CONFIG_GUIDEWAY_SHEET_TRACK_ID_KEY].toInt();
        int edge_id = m_guideway_sheet_object[CONFIG_GUIDEWAY_SHEET_EDGE_ID_KEY].toInt();
        int edge_start_offset = m_guideway_sheet_object[CONFIG_GUIDEWAY_SHEET_EDGE_START_OFFSET_KEY].toInt();

        ret_hash[CONFIG_GUIDEWAY_SHEET_TRACK_ID_KEY] = track_id;
        ret_hash[CONFIG_GUIDEWAY_SHEET_EDGE_ID_KEY] = edge_id;
        ret_hash[CONFIG_GUIDEWAY_SHEET_EDGE_START_OFFSET_KEY] = edge_start_offset;
    }

    return ret_hash;
}

ScriptReader::DataSheetInfo ScriptReader::getDataSheetConfig()
{
    // 读取曲线配置
    if (!m_data_sheet_object.isEmpty()) {
        QString sheetName = m_data_sheet_object[CONFIG_SHEET_NAME_KEY].toString();
        QJsonObject data_struct_obj = m_data_sheet_object[CONFIG_DATA_STRUCT_KEY].toObject();

        QHash<QString, int> data_dict;
        const auto keys = data_struct_obj.keys();
        for (auto const& key : keys) {
            auto value = data_struct_obj[key].toInt();
            data_dict[key] = value;
        }
        return {sheetName, data_dict};

        // QJsonArray sheets = m_data_sheet_object[CONFIG_SHEET_NAME_KEY].toArray();

        // for(auto const& sheet : std::as_const(sheets)) {
        //     ScriptReader::DataSheetInfo data_sheet_info;
        //     data_sheet_info.sheet_name = sheet.toString();

        //     int direction = data_struct_obj[CONFIG_DATA_SHEET_DIRECTION_KEY].toInt();
        //     int track_id = data_struct_obj[CONFIG_DATA_SHEET_TRACK_ID_KEY].toInt();
        //     int track_offset = data_struct_obj[CONFIG_DATA_SHEET_TRACK_OFFSET_KEY].toInt();
        //     int speed = data_struct_obj[CONFIG_DATA_SHEET_SPEED_KEY].toInt();

        //     data_sheet_info.data_struct.append(direction);
        //     data_sheet_info.data_struct.append(track_id);
        //     data_sheet_info.data_struct.append(track_offset);
        //     data_sheet_info.data_struct.append(speed);
        //     ret_list.append(data_sheet_info);
        // }
    } else {
        return {};
    }
}

QString ScriptReader::getCycleFeatures() const
{
    return m_log_file_object[CONFIG_CYCLE_FEATURES_KEY].toString();
}

QJsonArray ScriptReader::getCycleValues() const
{
    return m_log_file_object[CONFIG_CYCLE_VALUES_KEY].toArray();
}

QJsonArray ScriptReader::getUIConfig() const
{
    return m_ui_config_array;
}

int ScriptReader::getTrackIDCol() const
{
    return m_guideway_sheet_object[getUIConfig()[0].toString()].toInt();
}

QString ScriptReader::getComboboxVarNameFromLog() const
{
    return getUIConfig()[1].toString();
}


